import datetime
from jili.core.printlog import print
import pandas as pd
import matplotlib.pyplot as plt
from jili.core import sendemail as mail
from jili.data import db as dba
from jili.core.convert import converttype,originalname,arg2argkv
from jili.calc.status import status
from bs4 import BeautifulSoup
from jili.calc.operator import operator
class pairmatch(operator):#flag:higt low ch cl up down start 
    argkey=("pairfield","field")
    def __init__(self,*arg,**argkv):
        #self.datatype=["list"] #for list
        self.datatype=["dict"]
        super().__init__("pairmatch",pairmatch.argkey,arg,argkv)
    def run(self):
        toggle=[["high","low"],["check_high","check_low"],["sell","buy"]]
        field=[]
        if self.input:
            rst={}
            t=self.input[0]
            if "pairfield" in self.config.keys():
                toggle=self.config["pairfield"]
            if "field" in self.config.keys():
                field=self.config["field"]
            for tog in toggle:
                key=tog[0]+"-"+tog[1]
                rst[key]=dict(up=[],down=[])
            for k,v in t.items():
                flag=k[1]
                for tog in toggle:
                    key=tog[0]+"-"+tog[1]
                    if flag in tog:
                        if flag==tog[0]:
                            #down class state
                            tupl={}
                            tupl[flag]=v
                            rst[key]["down"].append(tupl)
                            #up classe state
                            if len(rst[key]["up"])>0:
                                tupl=rst[key]["up"][-1]
                                tupl[flag]=v
                                k0=tog[1]
                                v0=tupl[k0]
                                for f in field:
                                    keyf="delta"+f
                                    tupl[keyf]=v[f]-v0[f]
                        else:
                            #up class state
                            tupl={}
                            tupl[flag]=v
                            rst[key]["up"].append(tupl)
                            #down classe state
                            if len(rst[key]["down"])>0:
                                tupl=rst[key]["down"][-1]
                                tupl[flag]=v
                                k0=tog[0]
                                v0=tupl[k0]
                                for f in field:
                                    keyf="delta"+f
                                    if f=="timekey":
                                        tupl[keyf]=v[f]-v0[f]
                                    else:
                                        tupl[keyf]=v0[f]-v[f]
            for tog in toggle:
                key=tog[0]+"-"+tog[1]
                if not rst[key]["up"]:
                    del rst[key]["up"]
                if not rst[key]["down"]:
                    del rst[key]["down"]
                    if not rst[key]:
                        del rst[key]
            self.endcount()
            self.output.append(rst)
            super().run()
class paircalc(operator):#flag:higt low ch cl up down start 
    argkey=("pairfield","field")
    def __init__(self,*arg,**argkv):
        self.datatype=["dict"]
        super().__init__("paircalc",paircalc.argkey,arg,argkv)
    def run(self):
        toggle=[["high","low"],["check_high","check_low"],["sell","buy"]]
        field=[]
        if self.input:
            rst=self.input[0]
            if "pairfield" in self.config.keys():
                toggle=self.config["pairfield"]
            if "field" in self.config.keys():
                field=self.config["field"]
            report={}
            for tog in toggle:
                key=tog[0]+"-"+tog[1]
                if key in rst.keys():
                    for f in field:
                        keyf="delta"+f
                        if "up" in rst[key]:
                            key1=key+".up-"+f
                            report[key1]=[]
                            for i in rst[key]["up"]:
                                if keyf in i.keys():
                                    report[key1].append(i[keyf])
                        if "down" in rst[key]:
                            key1=key+".down-"+f
                            report[key1]=[]
                            for i in rst[key]["down"]:
                                if keyf in i.keys():
                                    report[key1].append(i[keyf])     
            for tog in toggle:
                key=tog[0]+"-"+tog[1]
                for f in field:
                    key1=key+".up-"+f
                    key2=key+".down-"+f
                    if key1 in report.keys():
                        if not report[key1]:
                            del report[key1]
                    if key2 in report.keys():
                        if not report[key2]:
                            del report[key2]
            self.endcount()
            self.output.append(report)
            super().run()
class descripstatistics(operator):#flag:higt low ch cl up down start 
    def __init__(self,*arg,**argkv):
        self.datatype=["DF"]
        super().__init__("descripstatistics",(),arg,argkv)
    def run(self):
        if self.input:
            t=self.input[0]
            rst=t.apply(status)
            self.endcount()
            self.output.append(rst)
            super().run()
class NewHighNewLow(operator):#flag:higt low ch cl up down start 
    argkey=("name","gap","field")
    def __init__(self,*arg,**argkv):
        #self.datatype=["list"] #for list
        self.datatype=["dict"]
        self.__lastflag=0
        self.__lastkey=""
        self.__direction=0
        super().__init__("NewHighNewLow",NewHighNewLow.argkey,arg,argkv)
    def run(self):
        if self.input:
            rst={}
            t=self.input[0]
            if "field" in self.config.keys():
                field=self.config["field"]
            else:
                field="LastPrice"
                self.config["field"]="LastPrice"
            gap=10
            if "gap" in self.config.keys():
                gap0=self.config["gap"]
                if isinstance(gap0,int):
                    gap=gap0
                else:
                    self.config["gap"]=10
            else:
                self.config["gap"]=10
            subject=field+"-gap"+str(gap)
            if "name" in self.config.keys():
                subject=self.config["name"]
            else:
                self.config["name"]=subject
            print(self.config)
            #k=0 #for list
            #for price in t: #for list
            for k, price in t.items():
                lastprice=price[field]
                if self.__direction==1:
                    if lastprice>=self.__lastflag:
                        self.__lastflag=lastprice
                        self.__lastkey=k
                        price[subject]=["up"]
                    else:
                        if (self.__lastflag-gap)>lastprice:#形成新高，判断新低；转向
                            self.__direction=-1
                            price[subject]=["check_high"]
                            rst[(k,"check_high")]=price
                            t[self.__lastkey][subject].append("high")
                            rst[(self.__lastkey,"high")]=t[self.__lastkey]
                            self.__lastflag=lastprice
                            self.__lastkey=k
                        else:
                            price[subject]=["up"]
                elif self.__direction==-1:
                    if lastprice<=self.__lastflag:
                        self.__lastflag=lastprice
                        self.__lastkey=k
                        price[subject]=["down"]
                    else:
                        if (self.__lastflag+gap)<lastprice:#形成新高，判断新低；转向
                            self.__direction=1
                            price[subject]=["check_low"]
                            rst[(k,"check_low")]=price
                            t[self.__lastkey][subject].append("low")
                            rst[(self.__lastkey,"low")]=t[self.__lastkey]
                            self.__lastflag=lastprice
                            self.__lastkey=k
                        else:
                            price[subject]=["down"]
                else:
                    self.__lastflag=lastprice
                    self.__lastkey=k
                    self.__direction=1
                    price[subject]=["start"]
                    rst[(k,"start")]=price
                self.counting()
                #k=k+1  #for list
            self.endcount()
            self.output.append(rst)
            super().run()
class NewHighNewLow1(operator):#flag:higt low ch cl up down start 
    argkey=("name","gap","field")
    def __init__(self,*arg,**argkv):
        #self.datatype=["list"] #for list
        self.datatype=["dict"]
        self.__lastflag=0
        self.__lastkey=""
        self.__direction=0
        super().__init__("NewHighNewLow",NewHighNewLow.argkey,arg,argkv)
    def run(self):
        if self.input:
            rst={}
            t=self.input[0]
            if "field" in self.config.keys():
                field=self.config["field"]
            else:
                field="LastPrice"
                self.config["field"]="LastPrice"
            gap=[10,5]
            if "gap" in self.config.keys():
                gap0=self.config["gap"]
                if isinstance(gap0,list):
                    gap=gap0
                else:
                    self.config["gap"]=[10,5]
            else:
                self.config["gap"]=[10,5]
            subject=field+"-gap"+str(gap[0])+str(gap[1])
            if "name" in self.config.keys():
                subject=self.config["name"]
            else:
                self.config["name"]=subject
            print(self.config)
            #k=0 #for list
            #for price in t: #for list
            for k, price in t.items():
                lastprice=price[field]
                if self.__direction==1:
                    if lastprice>=self.__lastflag:
                        self.__lastflag=lastprice
                        self.__lastkey=k
                        price[subject]=["up"]
                    else:
                        if (self.__lastflag-gap[0])>lastprice:#形成新高，判断新低；转向
                            self.__direction=-1
                            price[subject]=["check_high"]
                            rst[(k,"sell")]=price
                            t[self.__lastkey][subject].append("high")
                            rst[(self.__lastkey,"high")]=t[self.__lastkey]
                            self.__lastflag=lastprice
                            self.__lastkey=k
                        else:
                            price[subject]=["up"]
                elif self.__direction==-1:
                    if lastprice<=self.__lastflag:
                        self.__lastflag=lastprice
                        self.__lastkey=k
                        price[subject]=["down"]
                    else:
                        if (self.__lastflag+gap[0])<lastprice:#形成新高，判断新低；转向
                            self.__direction=1
                            price[subject]=["check_low"]
                            rst[(k,"check_low")]=price
                            t[self.__lastkey][subject].append("low")
                            rst[(self.__lastkey,"low")]=t[self.__lastkey]
                            self.__lastflag=lastprice
                            self.__lastkey=k
                        else:
                            price[subject]=["down"]
                else:
                    self.__lastflag=lastprice
                    self.__lastkey=k
                    self.__direction=1
                    price[subject]=["start"]
                    rst[(k,"start")]=price
                self.counting()
                #k=k+1  #for list
            self.endcount()
            self.output.append(rst)
            super().run()
class NewHighNewLow2(operator):#flag:higt low ch cl up down start 
    argkey=("name","gap","field")
    def __init__(self,*arg,**argkv):
        #self.datatype=["list"] #for list
        self.datatype=["dict"]
        self.__lastflag=0
        self.__lastkey=""
        self.__direction=0
        super().__init__("NewHighNewLow",NewHighNewLow.argkey,arg,argkv)
    def run(self):
        if self.input:
            rst={}
            t=self.input[0]
            if "field" in self.config.keys():
                field=self.config["field"]
            else:
                field="LastPrice"
                self.config["field"]="LastPrice"
            gap=[10,5]
            if "gap" in self.config.keys():
                gap0=self.config["gap"]
                if isinstance(gap0,list):
                    gap=gap0
                else:
                    self.config["gap"]=[10,5]
            else:
                self.config["gap"]=[10,5]
            subject=field+"-gap"+str(gap[0])+str(gap[1])
            if "name" in self.config.keys():
                subject=self.config["name"]
            else:
                self.config["name"]=subject
            print(self.config)
            #k=0 #for list
            #for price in t: #for list
            for k, price in t.items():
                lastprice=price[field]
                if self.__direction==1:
                    if lastprice>=self.__lastflag:
                        self.__lastflag=lastprice
                        self.__lastkey=k
                        price[subject]=["up"]
                    else:
                        if (self.__lastflag-gap[0])>lastprice:#形成新高，判断新低；转向
                            self.__direction=-1
                            price[subject]=["check_high"]
                            rst[(k,"check_high")]=price
                            t[self.__lastkey][subject].append("high")
                            rst[(self.__lastkey,"high")]=t[self.__lastkey]
                            self.__lastflag=lastprice
                            self.__lastkey=k
                        else:
                            price[subject]=["up"]
                elif self.__direction==-1:
                    if lastprice<=self.__lastflag:
                        self.__lastflag=lastprice
                        self.__lastkey=k
                        price[subject]=["down"]
                    else:
                        if (self.__lastflag+gap[1])<lastprice:#形成新高，判断新低；转向
                            self.__direction=1
                            price[subject]=["check_low"]
                            rst[(k,"check_low")]=price
                            t[self.__lastkey][subject].append("low")
                            rst[(self.__lastkey,"low")]=t[self.__lastkey]
                            self.__lastflag=lastprice
                            self.__lastkey=k
                        else:
                            price[subject]=["down"]
                else:
                    self.__lastflag=lastprice
                    self.__lastkey=k
                    self.__direction=1
                    price[subject]=["start"]
                    rst[(k,"start")]=price
                self.counting()
                #k=k+1  #for list
            self.endcount()
            self.output.append(rst)
            super().run()
def report_discrib(obj,field=[["high","low"],["close","open"]],cu="kline1dindex",db="kline1d",htmloremail="html"):
    field0=[]
    for i in field:
        for j in i:
            field0.append(j)
    ad=dba.getdb(cu,find={"obj":obj},field=field0,db=db,datatype="DF")
    loc_columuns=[]
    for i in field:
        f1=i[0]
        f2=i[1]
        name=i[0]+"-"+i[1]
        nameabs=name+".abs"
        loc_columuns.append(name)
        loc_columuns.append(nameabs)
        ad[name]=ad[f1]-ad[f2]
        ad[nameabs]=abs(ad[name])
    ads=ad.loc[:,loc_columuns]
    reportname="report."+obj+"."+cu
    if htmloremail=="html":
        report_to_html(reportname,ads)
    elif htmloremail=="email":
        report_to_email(reportname,ads)
    else:
        report_to_html(reportname,ads)
        report_to_email(reportname,ads)
def report_to_html(html,df,mode="w"):
    html0=html+".html"
    if mode=="w":
        f = open(html0,mode,encoding='utf8')
        h=headhtml(html)
    else:
        f = open(html0,mode,encoding='utf8')
        h=""
    pd.set_option('max_colwidth',200)
    rst=df.apply(status)
    h0 =rst.to_html()
    h=h+addtext(html+"统计描述如下","h1")
    h=h+addtable(h0)
    plt.rcParams['savefig.dpi'] = 300 #图片像素
    plt.rcParams['figure.dpi'] = 300 #分辨率
    for i in df.columns:
        plt.figure()
        plt.hist(df[i],bins=100)
        digname=str(id(df))+"."+i+".png"
        plt.savefig(digname)
        h=h+addtext(digname)
        h=h+addfig(digname)
    h=h+endhtml()
    for eachline in h:
         f.write(eachline)
    f.close()
def report_to_email(name,df,tomail=[]):
    h=headhtml(name)
    pd.set_option('max_colwidth',200)
    rst=df.apply(status)
    h0 =rst.to_html()
    h=h+addtext(name+"统计描述如下","h1")
    h=h+addtable(h0)
    plt.rcParams['savefig.dpi'] = 120 #图片像素
    plt.rcParams['figure.dpi'] = 120 #分辨率
    emailfig=[]
    for i in df.columns:
        plt.figure()
        plt.hist(df[i],bins=100)
        digname=str(id(df))+"."+i+".png"
        plt.savefig(digname)
        emailfig.append(digname)
    h=h+endhtml()
    mail.send("统计报告"+name,h,fig=emailfig,tomail=tomail)        
def headhtml(title):
    head0=""""<html>
        <head>
            <meta charset="utf-8">
            <title>"""+title+"""</title>
        </head>
        <body>"""
    return head0
def endhtml():
    head0="""
            </body>
        <html>"""
    return head0
def addtext(text,headtype="h4"):
    return """<div align="center">
            <"""+headtype+""" align="center">"""+text+"""</"""+headtype+""">
        </div>"""
def addtable(table):
    if not isinstance(table,pd.DataFrame):
        t=converttype(table,"df")
    else:
        t=table
    if isinstance(t,pd.DataFrame):
        pd.set_option('max_colwidth',200)
        a =t.to_html()
        a= """<div align="center">
                """+a+"""
            </div>"""
    else:
        a=""
    return a
def addfig(fig):
    return """<div align="center">
            <img src="""+fig+"""  alt="no fig" />
        </div>"""
def cutnotrade(tick,tradetime=[["21:00:00","23:00:00"],["09:00:00","15:00:00"]]):
    tradetime0=[]
    for i in tradetime:
        t=[]
        for j in i:
            b=datetime.datetime.strptime(j,"%H:%M:%S")
            b=b.time()
            t.append(b)
        tradetime0.append(t) 
    delkey=[]
    if isinstance(tick,dict):
        for k,i in tick.items():
            istrade=False
            for j in tradetime0:
                if i["timekey"].time()>=j[0] and i["timekey"].time()<=j[1]:
                    istrade=True
            if not istrade:
                delkey.append(k)
    for k in delkey:
        del tick[k]
